package com.punai.web.controller.cs;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.punai.common.annotation.Anonymous;
import com.punai.common.bos.RestResponse;
import com.punai.common.constant.CsRoleConstants;
import com.punai.common.constant.VerifyAccountConstants;
import com.punai.common.core.controller.BaseController;
import com.punai.common.core.domain.CommonConstants;
import com.punai.common.core.domain.entity.SysUser;
import com.punai.common.core.domain.model.LoginUser;
import com.punai.common.exception.ServiceException;
import com.punai.common.properties.SqliteSysProperties;
import com.punai.common.properties.SystemTypeProperties;
import com.punai.config.service.VersionService;
import com.punai.framework.web.service.TokenService;
import com.punai.system.bo.LoginGJUser;
import com.punai.system.bo.LoginUserRes;
import com.punai.system.bo.PerRule;
import com.punai.system.domain.SysWechatcomloginLog;
import com.punai.system.service.ApiRequest;
import com.punai.system.service.CsLinkRolePermissionService;
import com.punai.system.service.ISysUserService;
import com.punai.system.service.ISysWechatcomloginLogService;
import com.punai.system.util.WeChatComUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.*;

@RestController
@RequestMapping("/external/v1")
public class LoginApiController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(LoginApiController.class);
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ApiRequest apiRequest;
    @Autowired
    private TokenService tokenService;

    @Autowired
    private CsLinkRolePermissionService rolePermissionService;

    @Autowired
    private SystemTypeProperties systemTypeProperties;

    @Autowired
    private SqliteSysProperties sqliteSysProperties;

    @Autowired
    private VersionService versionService;

    @Autowired
    private WeChatComUtil weChatComUtil;

    @Autowired
    private ISysWechatcomloginLogService sysWechatcomloginLogService;

    /**
     * 获取用户盐
     * @param username
     * @return
     */
    @Anonymous
    @RequestMapping(value = "/verification/{username}", method = RequestMethod.GET)
    public RestResponse<Map<String, String>> getUserSalt(@PathVariable("username") String username) {
        try {
            SysUser user = sysUserService.selectByUserName(username);
            if (ObjectUtil.isNull(user)) {
                log.error("用户不存在!");
                return RestResponse.fail("用户不存在!", "");
            }
            return RestResponse.ok("接收成功", "", new HashMap<String, String>() {{
                put("salt", user.getSalt());
            }});
        } catch (Exception e) {
            log.error("external.getUsertoken.error", e);
            return RestResponse.fail("用户不存在!", e.getMessage());
        }
    }



    @Anonymous
    @RequestMapping(value = "/verification/{username}/{password}/{mac}", method = RequestMethod.GET)
    public RestResponse<LoginUserRes> getUsertoken(@PathVariable("username") String username, @PathVariable("password") String password, @PathVariable("mac") String mac) {
        try {
            SysUser user = sysUserService.selectByUserName(username);
            return getLoginUserResRestResponse(username, password, mac, user);
        } catch (Exception e) {
            log.error("external.getUsertoken.error", e);
            return RestResponse.fail("登录失败，请联系管理员！", e.getMessage());
        }
    }

    private RestResponse<LoginUserRes> getLoginUserResRestResponse(String username, String password, String mac, SysUser user) {
        // 试用账号 获取epId
        if (StrUtil.equals(user.getStatus(), CommonConstants.USER_STATUS_1)) {
            // log.error("登录失败,用户被停用！");
            return RestResponse.fail("登录失败,用户被停用！", "登录失败,用户被停用！");
        }
        String epId = systemTypeProperties.getEpId();
        if (StrUtil.isBlank(epId)) {
            // 账号问题
            log.error("账号无法识别!");
            return RestResponse.fail("账号无法识别!", "epId不存在!");
        }
        String dbPassword = user.getPassword();
        if (!StrUtil.equals(password,dbPassword)) {
            // 账号密码无法匹配
            log.error("账号密码无法匹配!");
            return RestResponse.fail("账号密码无法匹配!", "账号密码无法匹配!");
        }
        Integer usePlace = user.getUsePlace();
        if (!VerifyAccountConstants.ACCOUNT_PLACE.GJ.getCode().equals(usePlace) &&
                !VerifyAccountConstants.ACCOUNT_PLACE.TY.getCode().equals(usePlace)) {
            // 非工具账户   或者  非通用账号
            log.error("非工具/通用账号!");
            return RestResponse.fail("非工具/通用账号!", "非工具/通用账号!");
        }
        RestResponse<LoginUserRes> login = apiRequest.login(new LoginGJUser(epId, username, mac));
        if (login.getCode() != 1) {
            // 还需要获取用户的 工具角色 的  code 合集
            LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, new HashSet<>(), user.getCompanyId());
            String token = tokenService.createGJToken(loginUser);

            log.info("登录成功");
            LoginUserRes data = login.getData();
            data.setToken(token);

            Map<String, Set<String>> codes = rolePermissionService.getPerCodeByUserid(user.getUserId());
            PerRule rule = data.getRule();
            List<String> address = rule.getAddressList();
            List<String> industry = rule.getIndustryList();
            List<String> module = rule.getModuleList();
            List<String> tempList = rule.getTempList();
            Set<String> addressCodes = codes.get(CsRoleConstants.PermType.AddressList.getCode());
            if(CollUtil.isEmpty(addressCodes)){
                addressCodes = new HashSet<>();
            }
            Set<String> moduleCodes = codes.get(CsRoleConstants.PermType.ModuleList.getCode());
            if(CollUtil.isEmpty(moduleCodes)){
                moduleCodes = new HashSet<>();
            }
            Set<String> industryCodes = codes.get(CsRoleConstants.PermType.IndustryList.getCode());
            if(CollUtil.isEmpty(industryCodes)){
                industryCodes = new HashSet<>();
            }
            Set<String> tempCodes = codes.get(CsRoleConstants.PermType.TempList.getCode());
            if(CollUtil.isEmpty(tempCodes)){
                tempCodes = new HashSet<>();
            }
            rule.setAddressList(new ArrayList<>(CollectionUtil.intersection(address, addressCodes)));
            rule.setIndustryList(new ArrayList<>(CollectionUtil.intersection(industry, industryCodes)));
            rule.setModuleList(new ArrayList<>(CollectionUtil.intersection(module, moduleCodes)));
            rule.setTempList(new ArrayList<>(CollectionUtil.intersection(tempList, tempCodes)));
        }
        return login;
    }

    /*
     * 检查基本文件版本与系统库版本是否一致
     */
    @RequestMapping(value = "/version/{tableType}/{tableVersion}", method = RequestMethod.GET)
    public RestResponse get(@PathVariable("tableType") String tableType, @PathVariable("tableVersion") String tableVersion)  {
        try {
            Map<String, Object> version = versionService.getVersion(tableType);
            if (version.containsKey("success")) {
                if (version.get("success").toString().equals(tableVersion)) {
                    return RestResponse.ok("获取文件版本成功", "", new HashMap<String, Boolean>() {{
                        put("isnew", true);
                    }});
                }
                return RestResponse.ok("获取文件版本成功", "", new HashMap<String, Boolean>() {{
                    put("isnew", false);
                }});
            }
            return RestResponse.fail("获取文件版本失败", version.get("error").toString());
        } catch (Exception e) {
            log.error("external.getUsertoken.error", e);
            return RestResponse.fail("获取文件版本失败", e.getMessage());
        }

    }

    @RequestMapping(value = "/version/{tableType}", method = RequestMethod.GET)
    public void downloadFile(@PathVariable("tableType") String tableType, HttpServletRequest request, HttpServletResponse response) {
        try {
            String fileName = tableType;
            FileInputStream inputStream = null;
            String basePath = sqliteSysProperties.getBasePath();
            try {
                inputStream = new FileInputStream(new File(basePath,fileName));
                downloadFileAndName(fileName,inputStream, response);
            } catch (FileNotFoundException e) {
                throw new ServiceException(e.getMessage());
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    @Anonymous
    @RequestMapping(value = "/logout/{username}", method = RequestMethod.GET)
    public RestResponse<Map<String, String>> logout(@PathVariable("username") String username,HttpServletRequest request) {
        try {
            SysUser user = sysUserService.selectByUserName(username);
            if (ObjectUtil.isNull(user)) {
                log.error("登出失败");
                return RestResponse.fail("登出失败", "用户不存在");
            }
            String epId = systemTypeProperties.getEpId();
            RestResponse<Map<String, String>> response = apiRequest.logout(new LoginGJUser(epId, username));
            // 销毁token
            LoginUser loginUser = tokenService.getLoginUser(request);
            if (loginUser != null) {
                tokenService.delLoginUser(loginUser.getToken());
            }
            return response;
        } catch (Exception e) {
            log.error("external.getUsertoken.error", e);
            return RestResponse.fail("登出失败", e.getMessage());
        }
    }



    @Anonymous
    @GetMapping("/WeChatComLogin")
    public RestResponse WeChatCom(String code, String state, String appid,String macId, HttpServletRequest request){
        try {
            String weChatComUserid = weChatComUtil.getLoginUser(code);
            SysUser user = sysUserService.selectUserByQywxUserId(weChatComUserid);
            RestResponse<LoginUserRes> loginData = getLoginUserResRestResponse(user.getUserName(), user.getPassword(), macId, user);
            if(loginData.getCode() != 0){
                return loginData;
            }
            LoginUserRes data = loginData.getData();
            data.setUsername(weChatComUserid);
            SysWechatcomloginLog weChatComLoginLog = new SysWechatcomloginLog();
            weChatComLoginLog.setId(IdUtil.fastUUID());
            weChatComLoginLog.setLoginSuccess(true);
            weChatComLoginLog.setState(state);
            weChatComLoginLog.setUserId(user.getUserId()+"");
            weChatComLoginLog.setWeChatComUserid(weChatComUserid);
            weChatComLoginLog.setToken(data.getToken());
            weChatComLoginLog.setLoginUserResObj(data);
            weChatComLoginLog.setMacid(macId);
            weChatComLoginLog.setWeChatComCode(code);
            weChatComLoginLog.setCreateBy("tool-login");
            weChatComLoginLog.setUpdateBy("tool-login");
            weChatComLoginLog.setCreateTime(new Date());
            weChatComLoginLog.setUpdateTime(new Date());
            sysWechatcomloginLogService.save(weChatComLoginLog);
            return loginData;
        } catch (Exception e) {
            log.error("external.getUsertoken.error", e);
            return RestResponse.fail("登录失败，请联系管理员！", e.getMessage());
        }
    }


    /**
     * 工具端根据state获取工具权限
     */
    @Anonymous
    @GetMapping("/getRule/{state}")
    public RestResponse getRule(@PathVariable("state")String state){
        try {
            LoginUserRes res = sysWechatcomloginLogService.findRuleByState(state);
            return RestResponse.ok("获取成功!", "获取成功", res);
        }catch (Exception e){
            log.error("external.getRule.error", e);
            return RestResponse.fail("获取失败，请联系管理员！", e.getMessage());
        }
    }

}
